#include "stdafx.h"
#include "DriverIo.h"



ULONGLONG GetNumberFirst(ULONGLONG Number)
{
	Number &= 0x000000000F;
	return Number;
}

ULONGLONG ClearAttributeValues(ULONGLONG Number)
{

	Number &= 0x000000FFFFFFF000;
	return Number;
}

ULONGLONG GetPageAddress(ULONGLONG Last, ULONGLONG Next)
{
	Last = ClearAttributeValues(Last);
	Last = Last + Next * 8;
	return Last;
}

LONGLONG Get_Last_digit(ULONGLONG Addr)
{
	LONGLONG Tmp = Addr;
	Tmp &= 0x000000000F;
	Tmp *= 0x100000000;
	return Tmp;
}

PULONG64 Mapped_Memory_Addr(ULONGLONG Addr, int Mapped_len, int Catch, ULONG64 StartAddr)
{
	PULONG64 Temp = new ULONG64[Mapped_len];
	memcpy(Temp, (PVOID)(Addr + StartAddr), Mapped_len);
	return Temp;
}

NTSTATUS translate_Linear_address(ULONGLONG Linearaddress, ULONGLONG DirBase, int Catch, PULONGLONG PhyAddrV, ULONG64 StartAddr)
{

	VIRTUAL_ADDRESS virtualAddress = { 0 };
	if (DirBase <= 0)
	{
		return (NTSTATUS)100000;
	}

	virtualAddress.ulVirtualAddress = Linearaddress;
	PULONGLONG PLM4 = Mapped_Memory_Addr(DirBase, MEMORY_PAGE_MAX, Catch, StartAddr);

	if (PLM4 == NULL)
	{
		return GET_PTML4_ERROR;
	}
	if (PLM4[0] == 0)
	{
		return GET_PTML4_ERROR;
	}
	PULONGLONG PDPT = Mapped_Memory_Addr(GetPageAddress(PLM4[virtualAddress.stVirtualAddress.PLM4], virtualAddress.stVirtualAddress.PDPT), MEMORY_PAGE_MAX, Catch, StartAddr);
	if (PDPT == NULL)
	{
		return GET_PDPT_ERROR;
	}

	PULONGLONG PDT = Mapped_Memory_Addr(GetPageAddress(PDPT[0], virtualAddress.stVirtualAddress.PDT), MEMORY_PAGE_MAX, Catch, StartAddr);
	if (PDT == NULL)
	{
		return GET_PDT_ERROR;
	}

	PULONGLONG PT = Mapped_Memory_Addr(GetPageAddress(PDT[0], virtualAddress.stVirtualAddress.PT), MEMORY_PAGE_MAX, Catch, StartAddr);
	if (PT == NULL)
	{
		return GET_PT_ERROR;
	}



	*PhyAddrV = ClearAttributeValues(PT[0]) + virtualAddress.stVirtualAddress.offset + StartAddr;


	return 0;
}
DriverIo::DriverIo()
{
}


DriverIo::~DriverIo()
{
	if (m_Hande != NULL) {
		CloseHandle(m_Hande);
		m_Hande = NULL;
	}
}

BOOLEAN DriverIo::DriverInitialization()
{
	m_Hande = CreateFile(DEVICE_LINK_NAME,
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (m_Hande == INVALID_HANDLE_VALUE){
		return FALSE;
	}

	return TRUE;

	
}

ULONG64 DriverIo::R3Initialization()
{
	__FakeIoInfo m_FakeIoInfo;
	DWORD dwWrite = 0;
	ULONG64 RetData = 0;
	m_FakeIoInfo.Code =  0X100;
	m_FakeIoInfo.Flage =READPROCESSMEMORY;
	DeviceIoControl(m_Hande, READPROCESSMEMORY, &m_FakeIoInfo, sizeof(__FakeIoInfo), &RetData, sizeof(ULONG64), &dwWrite, NULL);
	m_StartAddr = RetData;
	return RetData;
}

ULONG64 DriverIo::SetProcess(DWORD Pid)
{
	ULONG64 RetData = 0;
	DWORD dwWrite = 0;
	__FakeIoInfo m_FakeIoInfo;
	m_FakeIoInfo.Code = 0x101;
	m_FakeIoInfo.Flage = READPROCESSMEMORY;
	m_FakeIoInfo.Pid = Pid;
	DeviceIoControl(m_Hande, READPROCESSMEMORY, &m_FakeIoInfo, sizeof(__FakeIoInfo), &RetData, sizeof(ULONG64), &dwWrite, NULL);
	m_Cr3 = RetData;
	return m_Cr3;
}

BOOLEAN DriverIo::ReadProcess_Me(ULONG_PTR Addr, ULONG_PTR Size, PVOID Buffer)
{
	ULONG_PTR Ba = 0;
	if (m_Cr3 == 0 || Addr == 0)
	{
	
		return FALSE;
	}
	NTSTATUS Status  = translate_Linear_address(Addr, m_Cr3, 0, &Ba, m_StartAddr);
	if (Ba == 0 || Status != 0)
	{
		return FALSE;
	}
	memcpy(Buffer, (PVOID)Ba, Size);
	return TRUE;
}

ULONG64 DriverIo::GetProcessStartAddr()
{
	__FakeIoInfo m_FakeIoInfo;
	ULONG64 RetData = 0;
	DWORD dwWrite = 0;

	m_FakeIoInfo.Code = 0x103;
	m_FakeIoInfo.Flage = READPROCESSMEMORY;
	m_FakeIoInfo.Pid = 0;
	DeviceIoControl(m_Hande, READPROCESSMEMORY, &m_FakeIoInfo, sizeof(__FakeIoInfo), &RetData, sizeof(ULONG64), &dwWrite, NULL);
	return RetData;
}
